package com.soft.process.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Attachment;
import org.activiti.engine.task.Task;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.soft.core.domain.ActivitiBaseEntity;
import com.soft.core.utils.BeanUtil;
import com.soft.core.utils.JobEnum;
import com.soft.core.utils.ProcessVariableEnum;
import com.soft.core.utils.StatusEnum;
import com.soft.core.utils.SystemConstant;
import com.soft.security.domain.Dept;
import com.soft.security.domain.User;

@Repository
@SuppressWarnings("unchecked")
public class ActivitiDao {
	
	private SessionFactory sessionFactory;
	private RuntimeService runtimeService;
	private HistoryService historyService;
	private TaskService taskService;
	
	@Resource
	public void setRuntimeService(RuntimeService runtimeService) {
		this.runtimeService = runtimeService;
	}

	@Resource
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	/**
	 * 启动流程
	 * @param entity
	 * @param definitionKey
	 */
	public void doStart(ActivitiBaseEntity entity, String definitionKey) {
		entity.setStatus(StatusEnum.start.getValue());
		sessionFactory.getCurrentSession().save(entity);
		
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put(ProcessVariableEnum.model.toString(), entity);
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(definitionKey, entity.getId()
				.toString(), variables);
		
		Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
		taskService.complete(task.getId());
	}

	/**
	 * 查询当前用户的部门主管
	 * @param userId
	 * @return
	 */
	public List<User> findDeptManager2User(Long userId) {
		User user = (User) sessionFactory.getCurrentSession().get(User.class, userId);
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(User.class);
		criteria.createAlias("depts", "d");
		criteria.createAlias("jobs", "j");
		criteria.add(Restrictions.eq("j.jobName", JobEnum.deptManager.getValue()));
		List<Long> userDepts = new ArrayList<Long>();
		for (Dept d : user.getDepts()) {
			userDepts.add(d.getId());
		}
		criteria.add(Restrictions.in("d.id", userDepts));
		return criteria.list();
	}
	
	/**
	 * 执行任务
	 * @param transition ：seqenceFlow的名字,用于驳回
	 * @param task       ：任务
	 * @param model      : 业务数据
	 * @param currentUser：申请人
	 * @param comment：审批意见
	 */
	public void doTask(String transition, Task task, Object model, User currentUser, String comment) {
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put(ProcessVariableEnum.transition.toString(), transition);

		if (SystemConstant.REQUEST_TASK.equals(task.getName())) {
			ActivitiBaseEntity m = (ActivitiBaseEntity) model;
			ActivitiBaseEntity entity = (ActivitiBaseEntity) sessionFactory.getCurrentSession().get(model.getClass(), m.getId());
			BeanUtil.copy(model, entity);
			sessionFactory.getCurrentSession().save(entity);
			variables.put(ProcessVariableEnum.model.toString(), entity);
		}
		
		taskService.claim(task.getId(), currentUser.getUserName());
		taskService.complete(task.getId(), variables);
		
		if (null != comment && !"".equals(comment.trim())) {
			Attachment attachment = taskService.createAttachment("comment", task.getId(), task.getProcessInstanceId(), currentUser.getUserName(), comment, "");
			taskService.saveAttachment(attachment);
		}
	}
	
	/**
	 * 查询流程实例的审批意见
	 * @param processInstance
	 * @return
	 */
	public List<Map<String, String>> getComments(String processInstanceId) {
		List<Attachment> attachments = taskService
				.getProcessInstanceAttachments(processInstanceId);
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for (Attachment comment : attachments) {
			Map<String, String> map = new HashMap<String, String>();
			HistoricTaskInstance t = historyService
					.createHistoricTaskInstanceQuery()
					.taskId(comment.getTaskId()).singleResult();
			String commentName = t.getName() + "(" + comment.getName() + ")";
			map.put("taskName", commentName);
			map.put("comment", comment.getDescription());
			list.add(map);
		}
		return list;
	}	

	@Resource
	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
		
	}

	@Resource
	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}
}
